﻿//-----------------------------------------------------------------------
// <copyright file="GetPictureCommand.cs">
//     Copyright © 2010. All rights reserved.
// </copyright>
// <author>Matt Lacey</author>
//-----------------------------------------------------------------------
using System;
using System.IO;
using System.IO.IsolatedStorage;
using System.Windows.Media.Imaging;
using Microsoft.Phone.Tasks;
using Newtonsoft.Json;

namespace PhoneGap.Plugins.Camera
{
    public class GetPictureCommand : PhoneGapCommand, IAsyncCommand
    {
        private string successCallback;
        private string errorCallback;
        private const String tempJPEG = "TempJpegFile.jpg";
        private const String tempPNG = "TempPngFile.png";

        private static CameraOptions objCameraOptions;

        public override void Execute(params string[] args)
        {
            this.HasCallback = false; // This uses an AsyncCallback

            this.successCallback = args[0];
            this.errorCallback = args[1];

            // args[2] contains a quality option but we ignore it in WP7
            objCameraOptions = JsonConvert.DeserializeObject<CameraOptions>(args[2]);

            try
            {
                // Tombstoning causes real problems at the moment, not least with subscribed events (like below), but also with just reloading the page
                // May need to reconsider how/if we wish to support this
                ChooserBase<PhotoResult> cct;
                if (objCameraOptions.SourceType == PictureSourceType.CAMERA)
                {
                    cct = new CameraCaptureTask();
                    cct.Completed += new EventHandler<PhotoResult>(cct_Completed);
                    cct.Show();
                }
                else if (objCameraOptions.SourceType == PictureSourceType.SAVEDPHOTOALBUM || objCameraOptions.SourceType == PictureSourceType.PHOTOLIBRARY)
                {
                    cct = new PhotoChooserTask();
                    cct.Completed += new EventHandler<PhotoResult>(cct_Completed);
                cct.Show();
            }
                else
                {
                    this.CallbackName = this.errorCallback;
                    this.CallbackArgs = new[] { "Invalid Source Type specified." };
                }
            }
            catch (Exception exc)
            {
                this.CallbackName = this.errorCallback;
                this.CallbackArgs = new[] { exc.Message };
            }
        }

        void cct_Completed(object sender, PhotoResult e)
        {
            if (e.Error == null)
            {
                this.CallbackName = this.successCallback;

                switch (e.TaskResult)
                {
                    case TaskResult.OK:
                        int streamLength = Convert.ToInt32(e.ChosenPhoto.Length);

                        if (objCameraOptions.DestinationType == DestinationType.DATA_URL)
                        {
                            byte[] fileData = new byte[streamLength + 1];
                        e.ChosenPhoto.Read(fileData, 0, streamLength);
                        e.ChosenPhoto.Close();

                        string base64 = Convert.ToBase64String(fileData);

                        this.CallbackArgs = new[] { base64 };
                        }
                        else if (objCameraOptions.DestinationType == DestinationType.FILE_URI)
                        {
                            if (EncodePicture2JpgFile(e.ChosenPhoto))
                            {
                                Uri fileUri = new Uri(tempJPEG, UriKind.Relative);
                                this.CallbackArgs = new[] { fileUri.ToString() };
                            }
                            else
                            {
                                this.CallbackName = this.errorCallback;
                                this.CallbackArgs = new string[] { "Error encoding image as JPG" };
                            }
                        }

                        SendAsyncResponse();
                        break;
                    default:
                        this.CallbackArgs = new[] { string.Empty };
                        break;
                }
            }
            else
            {
                this.CallbackName = this.errorCallback;
                this.CallbackArgs = new[] { e.Error.Message };
            }
        }

        private bool EncodePicture2JpgFile(Stream sourceStream)
        {
            try
            {
                // Create a virtual store and file stream. Check for duplicate tempJPEG files.
                var myStore = IsolatedStorageFile.GetUserStoreForApplication();
                if (myStore.FileExists(tempJPEG))
                {
                    myStore.DeleteFile(tempJPEG);
                }

                IsolatedStorageFileStream myFileStream = myStore.CreateFile("www/" + tempJPEG);

                BitmapImage bitmap = new BitmapImage();
                bitmap.CreateOptions = BitmapCreateOptions.None;
                bitmap.SetSource(sourceStream);

                // Create a new WriteableBitmap object and set it to the JPEG stream.
                WriteableBitmap wb = new WriteableBitmap(bitmap);

                // Encode the WriteableBitmap object to a JPEG stream.
                wb.SaveJpeg(myFileStream, objCameraOptions.TargetWidth, objCameraOptions.TargetHeight, 0, objCameraOptions.Quality);
                //wb.SaveJpeg(myFileStream, wb.PixelWidth, wb.PixelHeight, 0, 85);
                myFileStream.Close();
                return true;
            }
            catch (Exception ex)
            {
#if DEBUG
                System.Diagnostics.Debug.WriteLine(ex.Message + "\n" + ex.StackTrace);
#endif
                this.CallbackName = this.errorCallback;
                this.CallbackArgs = new[] { ex.Message };
                return false;
            }
        }

        public void SendAsyncResponse()
        {
            if (this.OnCommandCompleted != null)
            {
                this.OnCommandCompleted(null, this);
            }
        }

        public event EventHandler<PhoneGapCommand> OnCommandCompleted;
    }
}
